﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using HandyControl.Controls;
using IotClient.Entity;
using IotClient.VM;
using MQTTnet;
using MQTTnet.Client;

namespace IotClient.Unity
{
    public class MQTTUnity
    {
        public ClientSetting Setting { get; set; } = new ClientSetting();
        public Action<DeviceDataPack, string> OnReceived { get; set; }
        public Action<string, bool> LogCall;

        MqttFactory Factory = new MqttFactory();
        IMqttClient Client;
        Random rd = new Random();

        public string AutoPayload()
        {
            var data = new DeviceDataPack() { };
            data.data.a1 = (int)(rd.NextDouble() * 100);
            data.data.status = (int)(rd.NextDouble() * 100);
            return ToPayload(data);
        }

        public string ToPayload(DeviceDataPack deviceData)
        {
            string jsonString = JsonSerializer.Serialize(deviceData);
            return jsonString;
        }

        public bool Push(string Payload)
        {
            if (Client != null && Client.IsConnected)
            {
                var applicationMessage = new MqttApplicationMessageBuilder()
                    .WithTopic(Setting.PushTopic)
                    .WithPayload(Payload)
                    .Build();
                Client.PublishAsync(applicationMessage, CancellationToken.None).Wait();
                return true;
            }
            return false;
        }

        public void StartSubscribe(string topic)
        { // 订阅事件
            Client.ApplicationMessageReceivedAsync += MqttClient_ApplicationMessageReceivedAsync;
            Client.SubscribeAsync(topic).Wait();
        }

        private async Task MqttClient_ApplicationMessageReceivedAsync(
            MqttApplicationMessageReceivedEventArgs args
        )
        {
            var dat = args.ApplicationMessage.ConvertPayloadToString();
            if (!string.IsNullOrWhiteSpace(dat))
            {
                try
                {
                    var obj = JsonSerializer.Deserialize<DeviceDataPack>(dat);
                    string ClientId = null;
                    if (args.ApplicationMessage.Topic.Split("/") is string[] arr && arr.Length >= 4)
                        ClientId = arr[2];
                    OnReceived?.Invoke(obj, ClientId);
                }
                catch (Exception ex)
                {
                    LogCall($"接收不支持解析：{dat} \n=> {ex.Message}", true);
                }
            }
        }

        bool Eanble = false;

        public void ConnentCall(bool conn)
        {
            if (!conn)
            {
                Eanble = false;
                Client.DisconnectAsync().Wait();
                return;
            }
            if (string.IsNullOrWhiteSpace(Setting.Server))
            {
                MessageBox.Show("请填写服务器");
                return;
            }
            if (string.IsNullOrWhiteSpace(Setting.Username))
            {
                MessageBox.Show("请填写用户名");
                return;
            }
            if (string.IsNullOrWhiteSpace(Setting.Password))
            {
                MessageBox.Show("请填写密码");
                return;
            }
            if (string.IsNullOrWhiteSpace(Setting.ClientID))
            {
                MessageBox.Show("请填写客户端ID");
                return;
            }
            Client = Factory.CreateMqttClient();
            var mqttClientOptions = new MqttClientOptionsBuilder()
                .WithTcpServer(Setting.Server, Setting.Port)
                .WithClientId(Setting.ClientID)
                .WithCredentials(Setting.Username, Setting.Password)
                .Build();
            Client.ConnectAsync(mqttClientOptions, CancellationToken.None).Wait();
            Eanble = true;
            Setting.Status = true;
            Client.ConnectedAsync += MqttClient_ConnectedAsync;
            Client.DisconnectedAsync += MqttClient_DisconnectedAsync;
        }

        private Task MqttClient_DisconnectedAsync(MqttClientDisconnectedEventArgs arg)
        {
            Setting.Status = false;
            if (Eanble)
                Client.ReconnectAsync();
            return Task.CompletedTask;
        }

        private Task MqttClient_ConnectedAsync(MqttClientConnectedEventArgs arg)
        {
            Setting.Status = true;
            return Task.CompletedTask;
        }

        public static string GetTime()
        {
            return DateTime.Now.ToString("HH:mm:ss:fff");
        }
    }
}
